import math
import os
import numpy as np
# import matplotlib
# matplotlib.use('Agg')  # 切换到无 GUI 后端
import matplotlib.pyplot as plt
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.dates as mdates

from PIL import Image

# 设置字体以支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题


class ShowCarSpeed:
    def __init__(self):
        self.file_path = ''
        self.data = {}
        self.p85 = None

    def read_file(self, file_path):
        self.file_path = file_path
        self.get_data()
        self.show()
        self.clear()

    def read_file_true(self, file_path, true_time_list):
        self.file_path = file_path
        self.get_data()
        self.show_true(true_time_list)
        self.clear()

    def show(self):
        # 提取数据
        keys = list(self.data.keys())
        times = [datetime.strptime(time, '%H:%M') for time in keys]
        mean_speeds = [d['mean_speed'] for d in self.data.values() if 'mean_speed' in d]

        plt.plot(times, mean_speeds, marker='o', linestyle='-', color='r', label='平均速度')
        # 绘制85分位数线
        plt.axhline(y=self.p85, color='b', linestyle='--', label='85分位线')

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        # ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        if len(times) >= 10:
            start_time = times[10].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[10].replace(hour=23, minute=59, second=59, microsecond=999999)
        elif len(times) > 0:
            start_time = times[0].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[0].replace(hour=23, minute=59, second=59, microsecond=999999)
        else:
            start_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式

        # 设置Y轴每隔10进行显示
        y_min, y_max = ax.get_ylim()  # 获取当前Y轴的最小值和最大值
        # 找到最接近y_min但不大于y_min的10的倍数
        start = np.floor(y_min / 10) * 10
        # 找到最接近y_max但不小于y_max的10的倍数
        end = np.ceil(y_max / 10) * 10
        plt.yticks(np.arange(start, end + 1, 10))  # 设定Y轴的刻度间隔为10，并确保是整十

        # 添加标签和标题
        ax.set_xlabel('时间')
        ax.set_ylabel('速度值（千米/小时）')
        ax.set_title('小客车全天平均速度统计')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.file_path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.file_path).split('.')[0]
        output_filename = os.path.join(output_dir, file_name + '.png')
        plt.savefig(output_filename, dpi=200)
        # 关闭图表以释放内存
        plt.close()

    def show_true(self, true_time_list):
        # 提取数据
        keys = list(self.data.keys())
        times = [datetime.strptime(time, '%H:%M') for time in keys]
        mean_speeds = [d['mean_speed'] for d in self.data.values() if 'mean_speed' in d]

        plt.plot(times, mean_speeds, marker='o', linestyle='-', color='r', label='平均速度')
        # 绘制85分位数线
        plt.axhline(y=self.p85, color='b', linestyle='--', label='40km/h')

        for i in range(len(true_time_list["true_value_list"])):
            x1_line = true_time_list["true_value_list"][i][:5]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='black', linestyle='--')
        for i in range(len(true_time_list["detection_value_list"])):
            x1_line = true_time_list["detection_value_list"][i]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='green', linestyle='--')

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        # ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        # 设置X轴时间范围固定为00:00到23:59
        if len(times) >= 10:
            start_time = times[10].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[10].replace(hour=23, minute=59, second=59, microsecond=999999)
        elif len(times) > 0:
            start_time = times[0].replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = times[0].replace(hour=23, minute=59, second=59, microsecond=999999)
        else:
            start_time = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
            end_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式
        # 可选：添加网格线以提高可读性
        plt.grid(True, which='both', linestyle='--', linewidth=0.5)

        # 设置Y轴每隔10进行显示
        y_min, y_max = ax.get_ylim()  # 获取当前Y轴的最小值和最大值
        # 找到最接近y_min但不大于y_min的10的倍数
        start = np.floor(y_min / 10) * 10
        # 找到最接近y_max但不小于y_max的10的倍数
        end = np.ceil(y_max / 10) * 10
        plt.yticks(np.arange(start, end + 1, 10))  # 设定Y轴的刻度间隔为10，并确保是整十

        # 添加标签和标题
        # ax.set_xlabel('时间')
        ax.set_ylabel('速度值（千米/小时）')
        ax.set_title('小客车全天平均速度统计')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.file_path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.file_path).split('.')[0]
        output_filename = os.path.join(output_dir, file_name + '.png')
        plt.savefig(output_filename, dpi=200, bbox_inches='tight', transparent=False)
        # 关闭图表以释放内存
        plt.close()

    def get_data(self):
        df_up = pd.read_csv(self.file_path)
        data0 = df_up.to_dict(orient='records')
        # print(data0)
        self.data = {}
        value = []
        seconds = []
        for i in range(len(data0)):
            # if math.isnan(data0[i]['duration_seconds']):
            #     # value.append(0)
            #     seconds.append(0)
            # else:
            value.append(data0[i]['mean_speed'])
            seconds.append(data0[i]['duration_seconds'])
        # value_data = self.replace_zeros(value)
        # seconds_data = self.replace_zeros(seconds)
        for j in range(len(data0)):
            time = data0[j]['transtime_up'].split(' ')[1][:5]
            self.data[time] = {
                'mean_speed': value[j]*3.6,
                'duration_seconds': seconds[j]
            }

        # 计算85分位数
        # value = np.array(value)
        # 使用列表推导式移除NaN值
        # filtered_data = [x for x in value if not np.isnan(x)]
        # self.p85 = np.percentile(filtered_data, 85)
        self.p85 = 40
        # print(self.p85)

    def replace_zeros(self, data):
        n = len(data)
        prev_nonzero = None  # 前一个非0值的位置
        next_nonzero = 0     # 下一个非0值的位置
        for i in range(n):
            if data[i] == 0:
                # 如果当前位置是0，尝试向前找非0值
                if prev_nonzero is None:
                    for j in range(i - 1, -1, -1):
                        if data[j] != 0:
                            prev_nonzero = j
                            break
                # 同时尝试向后找非0值
                while next_nonzero < n and data[next_nonzero] == 0:
                    next_nonzero += 1
                if next_nonzero < n and data[next_nonzero] != 0:
                    # 当前位置是0，且已经找到了前后非0值
                    if (next_nonzero - prev_nonzero) > 2:
                        jiange = (data[next_nonzero] - data[prev_nonzero]) / (next_nonzero - prev_nonzero)
                        replacement_value = data[prev_nonzero] + jiange * (i - prev_nonzero)
                    else:
                        replacement_value = (data[prev_nonzero] + data[next_nonzero]) / 2.0
                    data[i] = replacement_value
            else:
                # 更新下一个非0值的位置
                prev_nonzero = i
                next_nonzero = i + 1
        return data

    def clear(self):
        self.data.clear()
        self.p85 = 0
        self.file_path = ''


if __name__ == '__main__':

    name = "G004251002000620010,G004251001000320010-20240404"
    path0 = r'D:\GJ\项目\事故检测\output\邻垫高速'
    path = os.path.join(path0, name, 'car_time_data.csv')

    showCarSpeed = ShowCarSpeed()
    showCarSpeed.read_file(path)
